/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package jogo;

import jogo.Entidade.TiroMovimento;
import java.awt.*;
import jogo.Entidade.Tiro;
import jogo.Entidade.Bola;
import jogo.Entidade.Explosao;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import jogo.Entidade.*;
import jogo.sprite.Sprite;
import jogo.sprite.SpriteStore;
import jogo.sprite.SpritesJogo;

/**
 *
 * @author Glauco
 */
public class FrmJogo extends javax.swing.JFrame
        implements Runnable {

    private boolean up = false, down = false, tiro = false;
    private SpriteStore sp;
    private SpritesJogo spriteJogo;
    private IVariaveisControle statusJogo;
    double senAngulo;
    double cosAngulo;
    double radianAngulo;

    /**
     * Creates new form FrmJogo
     */
    public FrmJogo() {
        this.setVisible(true);
        initComponents();
        spriteJogo = new SpritesJogo();

        createBufferStrategy(2);

        sp = SpriteStore.getInstance();
        sp.getSprite("sprit.png");
        sp.getSprite("GradiusSheet1.png");
        sp.getSprite("gradius_nes_assembled.png");
        sp.getSprite("nave.png");

        setup();

        Thread t = new Thread(this);
        t.start();
    }

    public FrmJogo(IVariaveisControle jogoStatusTmp) {
        statusJogo = jogoStatusTmp;

        this.setVisible(true);
        initComponents();
        spriteJogo = new SpritesJogo();

        createBufferStrategy(2);

        sp = SpriteStore.getInstance();
        sp.getSprite("sprit.png");
        sp.getSprite("GradiusSheet1.png");
        sp.getSprite("gradius_nes_assembled.png");
        sp.getSprite("nave.png");
        sp.getSprite("rockPlanet256.png");

        setup();

        Thread t = new Thread(this);
        t.start();
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyPressed(java.awt.event.KeyEvent evt) {
                formKeyPressed(evt);
            }
            public void keyReleased(java.awt.event.KeyEvent evt) {
                formKeyReleased(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 400, Short.MAX_VALUE)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 300, Short.MAX_VALUE)
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void formKeyPressed(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_formKeyPressed

        if (evt.getKeyCode() == KeyEvent.VK_UP) {
            up = true;
        }

        if (evt.getKeyCode() == KeyEvent.VK_DOWN) {
            down = true;
        }

        if (evt.getKeyCode() == KeyEvent.VK_SPACE) {
            tiro = true;
        }

    }//GEN-LAST:event_formKeyPressed

    private void formKeyReleased(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_formKeyReleased

        if (evt.getKeyCode() == KeyEvent.VK_UP) {
            up = false;
        }

        if (evt.getKeyCode() == KeyEvent.VK_DOWN) {
            down = false;
        }

        if (evt.getKeyCode() == KeyEvent.VK_SPACE) {
            tiro = false;
        }

        if (evt.getKeyCode() == KeyEvent.VK_ESCAPE) {
            statusJogo.setJogoStatusEnum(JogoStatusEnum.Pause);
            //Abrir for de pause
        }

    }//GEN-LAST:event_formKeyReleased

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        /*
         * Set the Nimbus look and feel
         */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /*
         * If Nimbus (introduced in Java SE 6) is not available, stay with the
         * default look and feel. For details see
         * http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
         */
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(FrmJogo.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(FrmJogo.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(FrmJogo.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(FrmJogo.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        //</editor-fold>

        /*
         * Create and display the form
         */
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new FrmJogo().setVisible(true);
            }
        });
    }
    // Variables declaration - do not modify//GEN-BEGIN:variables
    // End of variables declaration//GEN-END:variables

    @Override
    public void run() {

        ArrayList<Elemento> elementos = new ArrayList<>();
        ArrayList<Elemento> remover = new ArrayList<>();
        ArrayList<Explosao> explosao = new ArrayList<>();
        ArrayList<Explosao> removerExplosao = new ArrayList<>();

        int x, y, red, green, blue;

        //Os sprites começam em 0
        Sprite stmp = spriteJogo.SpriteNaveEstatica(0);

        Nave nave = new Nave(stmp, 70, 350, 200, 0, 0);
        elementos.add(nave);

        stmp = spriteJogo.SpriteAsteroideEstatico(0);
        Asteroide ast = new Asteroide(stmp, 150, 256, 256, 0, 0);
        elementos.add(ast);

        Colisao colisao = new Colisao();
        colisao.setWidth(800);
        colisao.setHeight(600);


        long ultimoTiro = System.currentTimeMillis();
        long tempoEntreTiros = 300;
        long tiroTempo;
        boolean fim = false;
        int indexAsteroid = 0;


        while (true) {

            Graphics2D g = (Graphics2D) getBufferStrategy().getDrawGraphics();
            Graphics2D g2 = (Graphics2D) getBufferStrategy().getDrawGraphics();

            g.setColor(Color.BLACK);
            g.fillRect(0, 0, getWidth(), getHeight());

            g2.setColor(Color.BLACK);
            g2.fillRect(0, 0, getWidth(), getHeight());



            if (up) {

                for (Elemento e : elementos) {
                    if (e instanceof Nave) {
                        if (e.getAngulo() / 2 > -90) {
                            e.setAngulo(e.getAngulo() - 3);
                        }
                    }
                }

            } else if (down) {

                for (Elemento e : elementos) {
                    if (e instanceof Nave) {

                        if (e.getAngulo() / 2 < 90) {
                            e.setAngulo(e.getAngulo() + 3);
                        }
                    }
                }

            }


            if (tiro) {
                tiroTempo = System.currentTimeMillis();

                if (ultimoTiro + tempoEntreTiros < tiroTempo) {


                    ultimoTiro = tiroTempo;
                    stmp = spriteJogo.SpriteTiro(0);

                    //Construtor default para poder compilar
                    //Os valores do tiro serão setados abaicxo
                    Tiro t = new Tiro();

                    for (Elemento e : elementos) {
                        if (e instanceof Nave) {

                            CalculaSenCosDoAngulo(e);

                            t = new Tiro(stmp, e.getX() + (int) (cosAngulo),
                                    dy(e.getY() - 100 + (int) (senAngulo)),
                                    stmp.getWidth(), (7 + (100 / 50)) * (cosAngulo), -1 * (7 + (100 / 50)) * senAngulo);
                        }

                    }

                    elementos.add(t);
                }
            }

            //Verifica se tiro entrou no campo gravitacional
            indexAsteroid = GetAsteroidIndex(elementos);
            for (Elemento e : elementos) {
                if (e.isMovimento()) {
                    if (e instanceof Tiro) {
                        if (colisao.ColisaoTiroAtmosfera((Tiro) e, (Asteroide) elementos.get(indexAsteroid))) {
//                            gravityForce = true;
                            ((Tiro) e).setMaxvx(100);
                            ((Tiro) e).setMaxvy(100);

                            colisao.TiroDentroCampoGravitacional((Tiro) e, (Asteroide) elementos.get(indexAsteroid));
                            colisao.Gravitacao((Tiro) e, (Asteroide) elementos.get(indexAsteroid));

                        }
                    }

                    //TODO: CONCERTAR COLISAO ASTEROIDE TIRO
//                    if (colisao.ColisaoTiroAsteroide((Tiro) e, (Asteroide) elementos.get(indexAsteroid))) {
//                        ((Tiro) e).setMovimento(false);
//                        ((Tiro) e).setMovimento(0, 0);
//                        ((Tiro) e).setVivo(false);
//                    }

                    if (colisao.TiroForaCenario((Tiro) e)) {
                        ((Tiro) e).setMovimento(false);
                        ((Tiro) e).setMovimento(0, 0);
                        ((Tiro) e).setVivo(false);

                    }
                }


            }



            //Foi abistraido o mover da clase elemento
            for (Elemento e : elementos) {
                if (e.isMovimento()) {
                    if (e instanceof TiroMovimento) {
                        ((TiroMovimento) e).mover();
                    }

                    if (e instanceof NaveMovimento) {
                        ((NaveMovimento) e).mover();
                    }
                }
            }



            for (Elemento b : elementos) {
                if (b instanceof Nave) {
                    b.desenhar(g2);
                } else {
                    b.desenhar(g);
                }
            }


            for (Elemento b : elementos) {

                if (b.getX() > getWidth()) {
                    //b.setIncX(-1);
                    remover.add(b);
                }

                if (b.getY() > getHeight()) {
                    //b.setIncX(-1);
                    remover.add(b);
                }

                if (b.getX() <= 0) {
                    remover.add(b);
                    //b.setIncX(1);
                }
                if (b.getY() <= 0) {
                    remover.add(b);
                    //b.setIncX(1);
                }

            }


            elementos.removeAll(remover);
            remover.clear();


            g.dispose();
            g2.dispose();

            getBufferStrategy().show();


            try {
                Thread.sleep(10);
            } catch (InterruptedException ex) {
                Logger.getLogger(FrmJogo.class.getName()).log(Level.SEVERE, null, ex);
            }

        }

    }

    void setup() {
        this.setSize(800, 600);
    }

    private int GetAsteroidIndex(ArrayList<Elemento> elementos) {
        int index = 0;

        for (Elemento e : elementos) {
            if (e instanceof Asteroide) {
                return index;

            }
            index++;
        }
        return index;
    }

    private int dy(int i) {
        return 600 - i;
    }

    private void CalculaSenCosDoAngulo(Elemento e) {
        radianAngulo = -1 * e.getAngulo() / 2 * Math.PI / 180.0;
        senAngulo = Math.sin(radianAngulo);
        cosAngulo = Math.cos(radianAngulo);
    }
}
